#!/user/bin/env python
# -*- coding: utf-8 -*-
''' 
Author: Sjy
LastEditTime: 2024-11-15 09:58:15
Description: 对 toolbox 的扩展
'''

__all__= []


from PyQt5 import QtCore, QtGui, QtWidgets


class ListToolBox(QtWidgets.QToolBox):
    """快速根据配置文件生成工具箱 每个子widget 都是一个 QListWidget 
    json = [
        {
            "title":"工具箱1",
            "name":"toolbox1",
            "items":[
                {
                    "title":"item1",
                    "name":"item1",
                    "dbClick":lambda: print("item1")
                }
            ]
        }
    ]
    """

    def __init__(self, json:list=[], parent=None):
        super(ListToolBox, self).__init__(parent)
        self.__params=json
        self.__init_config()
        self.__init_ui(json)
        self.__init_signals()
        
    def __init_config(self):    
        # 先移除默认的layout
        vbox = self.layout()
        # 设置内边距都是0
        vbox.setContentsMargins(1, 1, 1, 1)
        vbox.setSpacing(2)
        vbox.setAlignment(QtCore.Qt.AlignTop)
        # self.setAutoFillBackground(True)
        # self.setInputMethodHints(QtCore.Qt.ImhNone)
        # self.setFrameShape(QtWidgets.QFrame.StyledPanel)
        # self.setFrameShadow(QtWidgets.QFrame.Sunken)
        style = QtWidgets.QApplication.instance().style()
        self.__icon_down = style.standardIcon(QtWidgets.QStyle.SP_TitleBarUnshadeButton)
        # 获取折叠时的图标
        self.__icon_up = style.standardIcon(QtWidgets.QStyle.SP_TitleBarShadeButton)
    def __init_ui(self, json:list=[]):
        for item in json:
            widget = QtWidgets.QListWidget()
            widget.setMinimumHeight(20)
            widget.setSizeAdjustPolicy(QtWidgets.QListWidget.AdjustToContents)

            # 设置 listWidget 的高度适应内容高度
            # widget.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
            # 设置 QListWidget 的 policy 规则为适应内容高度
            # widget.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
            widget.itemDoubleClicked.connect(lambda *args, action=self.__run_list_item_dbclick ,items=item.get("items") or [], widget=widget: action(widget, items))
            self.addItem(self.__init_page(widget) , item.get("title"))
            for subItem in item.get("items") or []:
                listItem = QtWidgets.QListWidgetItem(subItem.get("title"))
                listItem.setData(QtCore.Qt.UserRole, subItem.get("name"))
                widget.addItem(listItem)
        self.__change_icon(self.currentIndex())
    def __init_page(self, widget:QtWidgets.QWidget):
        """初始化页面"""
        gWidget = QtWidgets.QWidget()
        vbox = QtWidgets.QVBoxLayout()
        vbox.setSpacing(5)
        vbox.setContentsMargins(5, 5, 5, 5)
        vbox.addWidget(widget)
        gWidget.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
        gWidget.setLayout(vbox)
        # 属性必须放置在布局之后 否则容易出现闪烁情况（闪烁的原因是这个显示了但是容器还未布局，带布局好之后回归到布局位置造成的闪烁现象）
        return gWidget
    def __init_signals(self):
        # 初始化时不允许执行信号
        self.blockSignals(True)
        self.currentChanged.connect(lambda index: self.__change_icon(index))
        self.currentChanged.connect(lambda index: self.__run_action(index))
        self.blockSignals(False)
        # 因为信号被中断了 因此需要默认执行第一个
        self.__run_action(0)
    
    def __change_icon(self, index:int):
        """当前状态改变了,更换图标"""
        if index < 0: return
        self.setItemIcon(index, self.__icon_down) 
        for i in range(self.count()):
            if i != index:
                self.setItemIcon(i, self.__icon_up)
    
    def __run_action(self, index:int):
        """运行当前的action"""
        if index < 0: return
        action = self.__get_index_action(index)
        if action:
            action()
    def __get_index_action(self, index:int):
        """获取当前的action"""
        params = self.__params 
        if index < 0 or index >= len(params): return None
        item = params[index] or {}
        return item.get("action")
    
    def __run_list_item_dbclick(self, widget:QtWidgets.QListWidget, items:list):
        """运行当前的action"""
        index = widget.currentIndex()
        row = index.row()
        if row < 0 or row >= len(items): return
        action= (items[row] or {}).get("dbClick")
        if action:
            action()



class ToolBoxContainer(QtWidgets.QWidget):
    def __init__(self, params:dict={}, toolBox:QtWidgets.QToolBox=ListToolBox, parent=None):
        super(ToolBoxContainer, self).__init__(parent)
        self.__init_ui(params, toolBox)

    def __init_ui(self, params:dict={}, toolBox:QtWidgets.QToolBox=ListToolBox):
        vbox = QtWidgets.QVBoxLayout()
        vbox.setSpacing(0)
        vbox.setContentsMargins(0, 0, 0, 0)
        self.setLayout(vbox)
        self.__toolBox = toolBox(params)
        vbox.addWidget(self.__toolBox)


if  __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    json = [
        {
            "title":"导入模型",
            "name":"import",
            "action":lambda: print("import")
        },
        {
            "title":"工具箱2",
            "name":"toolbox2",
            "items":[
                {
                    "title":"工具箱2-0",
                    "name":"item2",
                    "dbClick":lambda : print("工具箱2-0")
                },
                {
                    "title":"工具箱2-1",
                    "name":"item2",
                    "dbClick":lambda : print("工具箱2-1")
                }
            ]
        },
    ]
    w = ListToolBox(json)
    w.show()
    sys.exit(app.exec_())